/*********************\
* Author:Dzlua
* QQ:505544956
* Time:2017/03/14
\**********************/
#include "StdAfx.h"

namespace DuiLib {

SDEngine* SDEngine::m_ptr = nullptr;

SDEngine* SDEngine::Interface()
{
    if (nullptr == m_ptr) {
        m_ptr = new SDEngine;
    }
    return m_ptr;
}

SDEngine::SDEngine() 
    : m_wnds(nullptr), m_script(nullptr),
      m_bAutoDeleteScript(false)
{
    m_strErr.clear();
    m_wnds = new SDWndMap;
}

SDEngine::~SDEngine()
{
    if (m_wnds) {
        delete m_wnds;
        m_wnds = nullptr;
    }

    if (m_bAutoDeleteScript && m_script) {
        delete m_script;
        m_script = nullptr;
    }
}

bool SDEngine::Init(HINSTANCE hInst)
{
	if(FAILED( ::CoInitialize(NULL) )) return false;

    if (NULL == hInst) hInst = GetModuleHandle(NULL);
    this->SetInstance(hInst);
    return true;
}

void SDEngine::Quit()
{
    this->RemoveAllWindow();
    
    if (m_script) {
        m_script->Quit();
    }

    if (m_ptr) {
        delete m_ptr;
        m_ptr = nullptr;
    }
    
    ::CoUninitialize();
}

void SDEngine::SetStript(SDIScript* script, bool bAutoDelete /*= true*/)
{
    if (m_script) {
        m_script->Quit();
        if (m_bAutoDeleteScript) {
            delete m_script;
            m_script = nullptr;
        }
    }

    if (script) {
        m_script = script;
        m_bAutoDeleteScript = bAutoDelete;
    }
}

SDIScript* SDEngine::GetStript()
{
    return m_script;
}

void SDEngine::SetError(SDTString err)
{
    m_strErr = err;
}

SDTString SDEngine::GetError()
{
    return m_strErr;
}

//--------------------------------------//
SDWindow* SDEngine::AddWindow(SDWindow* wnd, bool bAutoDelete /*= true*/)
{
    if (!wnd) return wnd;

    SDWndMap::iterator it;
    for (it = m_wnds->begin(); it != m_wnds->end(); ++it) {
        if((*it) == wnd) {
            return (*it);
        }
    }

    wnd->SetAutoDelete(bAutoDelete);
    m_wnds->push_back(wnd);
    return wnd;
}

void SDEngine::RemoveWindow(SDWindow* wnd)
{
    if (!wnd) return;
    SDWndMap::iterator it;
    for (it = m_wnds->begin(); it != m_wnds->end(); ++it) {
        if((*it) == wnd) {
            goto FIND;
        }
    }
    return;
FIND:
    if (wnd->GetHWND()) {
        ::DestroyWindow(wnd->GetHWND());
        return;
    }

    m_wnds->erase(it);
    if (wnd->IsAutoDelete()) {
        delete wnd;
    }
    
    ::PostQuitMessage(0);
}

void SDEngine::RemoveAllWindow()
{
    SDWndMap::iterator it;
    for (it = m_wnds->begin(); it != m_wnds->end();) {
        if(!(*it)->GetHWND()) {
            it = m_wnds->erase(it);
            if ((*it)->IsAutoDelete()) {
                delete (*it);
            }
        } else {
            ++it;
            ::DestroyWindow((*it)->GetHWND());
        }
    }
    ::PostQuitMessage(0);
}

int SDEngine::WindowsCount()
{
    return m_wnds->size();
}

SDWindow* SDEngine::WindowAt(int idx)
{
    if (idx < 0 || idx >= m_wnds->size()) return nullptr;
    return m_wnds->at(idx);
}

SDWindow* SDEngine::FindWindow(LPCTSTR pstrName)
{
    if (!pstrName) return nullptr;
    CDuiString name = pstrName;
    if (name.IsEmpty()) return nullptr;
    
    SDWndMap::iterator it;
    for (it = m_wnds->begin(); it != m_wnds->end(); ++it) {
        if( name == (*it)->GetName()) {
            return (*it);
        }
    }
    return nullptr;
}

SDWindow* SDEngine::FindWindow(HWND hWnd)
{
    if (!hWnd) return nullptr;
    SDWndMap::iterator it;
    for (it = m_wnds->begin(); it != m_wnds->end(); ++it) {
        if(hWnd == (*it)->GetHWND()) {
            return (*it);
        }
    }
    return nullptr;
}

SDWindow* SDEngine::FindWindow(CPaintManagerUI* pm)
{
    if (!pm) return nullptr;
    SDWndMap::iterator it;
    for (it = m_wnds->begin(); it != m_wnds->end(); ++it) {
        if(pm == (*it)->GetPaintManager()) {
            return (*it);
        }
    }
    return nullptr;
}

//--------------------------------------//

HINSTANCE SDEngine::GetInstance()
{
    return CPaintManagerUI::GetInstance();
}

CDuiString SDEngine::GetInstancePath()
{
    return CPaintManagerUI::GetInstancePath();
}

CDuiString SDEngine::GetCurrentPath()
{
    return CPaintManagerUI::GetCurrentPath();
}

HINSTANCE SDEngine::GetResourceDll()
{
    return CPaintManagerUI::GetResourceDll();
}

const CDuiString& SDEngine::GetResourcePath()
{
    return CPaintManagerUI::GetResourcePath();
}

const CDuiString& SDEngine::GetResourceZip()
{
    return CPaintManagerUI::GetResourceZip();
}

const CDuiString& SDEngine::GetResourceZipPwd()
{
    return CPaintManagerUI::GetResourceZipPwd();
}

bool SDEngine::IsCachedResourceZip()
{
    return CPaintManagerUI::IsCachedResourceZip();
}

HANDLE SDEngine::GetResourceZipHandle()
{
    return CPaintManagerUI::GetResourceZipHandle();
}

void SDEngine::SetInstance(HINSTANCE hInst)
{
    CPaintManagerUI::SetInstance(hInst);
}

void SDEngine::SetCurrentPath(LPCTSTR pStrPath)
{
    CPaintManagerUI::SetCurrentPath(pStrPath);
}

void SDEngine::SetResourceDll(HINSTANCE hInst)
{
    CPaintManagerUI::SetResourceDll(hInst);
}

void SDEngine::SetResourcePath(LPCTSTR pStrPath)
{
    CPaintManagerUI::SetResourcePath(pStrPath);
}

void SDEngine::SetResourceZip(LPVOID pVoid, unsigned int len, LPCTSTR password)
{
    CPaintManagerUI::SetResourceZip(pVoid, len, password);
}

void SDEngine::SetResourceZip(LPCTSTR pstrZip, bool bCachedResourceZip, LPCTSTR password)
{
    CPaintManagerUI::SetResourceZip(pstrZip, bCachedResourceZip, password);
}

void SDEngine::SetResourceType(int nType)
{
    CPaintManagerUI::SetResourceType(nType);
}

int SDEngine::GetResourceType()
{
    return CPaintManagerUI::GetResourceType();
}

bool SDEngine::GetHSL(short* H, short* S, short* L)
{
    return CPaintManagerUI::GetHSL(H, S, L);
}

void SDEngine::SetHSL(bool bUseHSL, short H, short S, short L) // H:0~360, S:0~200, L:0~200 
{
    CPaintManagerUI::SetHSL(bUseHSL, H, S, L);
}

void SDEngine::ReloadSkin()
{
    CPaintManagerUI::ReloadSkin();
}

CPaintManagerUI* SDEngine::GetPaintManager(LPCTSTR pstrName)
{
    return CPaintManagerUI::GetPaintManager(pstrName);
}

CStdPtrArray* SDEngine::GetPaintManagers()
{
    return CPaintManagerUI::GetPaintManagers();
}

bool SDEngine::LoadPlugin(LPCTSTR pstrModuleName)
{
    return CPaintManagerUI::LoadPlugin(pstrModuleName);
}

CStdPtrArray* SDEngine::GetPlugins()
{
    return CPaintManagerUI::GetPlugins();
}

void SDEngine::MessageLoop()
{
    //ensure to quit if not window.
    ::PostQuitMessage(0);
    
    MSG msg = { 0 };
    while( ::GetMessage(&msg, NULL, 0, 0) || (this->WindowsCount() > 0) ) {
        if( !CPaintManagerUI::TranslateMessage(&msg) ) {
            ::TranslateMessage(&msg);
            try{
                ::DispatchMessage(&msg);
            } catch(...) {
                DUITRACE(_T("EXCEPTION: %s(%d)\n"), __FILET__, __LINE__);
#ifdef _DEBUG
                throw "CPaintManagerUI::MessageLoop";
#endif
            }
        }
    }
}

bool SDEngine::TranslateMessage(const LPMSG pMsg)
{
    return CPaintManagerUI::TranslateMessage(pMsg);
}

void SDEngine::Term()
{
    CPaintManagerUI::Term();
}

void SDEngine::ReloadSharedImages()
{
    CPaintManagerUI::ReloadSharedImages();
}

void SDEngine::SetAllDPI(int iDPI)
{
    CPaintManagerUI::SetAllDPI(iDPI);
}

}